package xyz.icxl.android.architecture.data.net.okhttp.interceptors
import com.safframework.log.L
import okhttp3.FormBody
import okhttp3.Interceptor
import okhttp3.MultipartBody
import okhttp3.Response
import okhttp3.ResponseBody.Companion.toResponseBody
import okio.Buffer
import org.json.JSONArray
import org.json.JSONException
import org.json.JSONObject
import java.net.URLDecoder
import java.util.*

/**
 * 文件描述：日志请求拦截器
 *
 * 文件创建人：ChenXinLei
 *
 * 文件创建人联系方式：502616659(QQ)
 *
 * 创建时间：2020 年 04月 27 日
 *
 * 文件版本：v1.0
 *
 * 版本描述：创建文件
 */
class LogInterceptor : Interceptor{
    override fun intercept(chain: Interceptor.Chain): Response {
        val request  = chain.request()
        val startTime = System.currentTimeMillis()
        val response = chain.proceed(request)
        val mediaType = response.body?.contentType()
        val content = response.body?.string()
        val method = request.method
        val logSb = StringBuffer()
        logSb.append("\n|").append("------------------------------------START------------------------------------")
        logSb.append("\n|").append(method).append("\t -> \t").append(request.url)
        val parameters = StringBuffer()
        if ("POST" == method){
            if (request.body is FormBody){
                val body = request.body as FormBody
                for (i in 0 until body.size){
                    parameters.append(body.encodedName(i))
                        .append(":")
                        .append(body.encodedValue(i))
                        .append("\t")
                    if (i%3==0&&i!=0){
                        parameters.append("\n")
                    }
                }
            }else if (request.body is MultipartBody){
                val buffer = Buffer()
                request.body?.writeTo(buffer)
                val bodyHex = buffer.readByteString().hex()
                if (bodyHex.length>1000){
                    parameters.append("body->${bodyHex.substring(0,3)}...${bodyHex.substring(bodyHex.length-6)}")
                }else{
                    parameters.append("body->${bodyHex}")
                }
                parameters.append("\n")
            }else{
                val buffer = Buffer()
                request.body?.writeTo(buffer)
                parameters.append("body->${buffer.readUtf8()}")
                parameters.append("\n")
            }
        }else{
            val parameterStr =request.url.encodedQuery
            if (!parameterStr.isNullOrEmpty()){
                val mapRequest = HashMap<String, String>()
                val arrSplit: Array<String>?
                arrSplit = parameterStr.split("[&]".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
                for (strSplit in arrSplit) {
                    var arrSplitEqual: Array<String>?
                    arrSplitEqual = strSplit.split("[=]".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
                    //解析出键值
                    if (arrSplitEqual.size > 1) {
                        //正确解析
                        mapRequest[arrSplitEqual[0]] = arrSplitEqual[1]
                    } else {
                        if (arrSplitEqual[0] !== "") {
                            //只有参数没有值，不加入
                            mapRequest[arrSplitEqual[0]] = ""
                        }
                    }
                }
                for ((i, key) in mapRequest.keys.withIndex()){
                    parameters.append(key).append("=").append(URLDecoder.decode(mapRequest[key],"UTF-8")).append("\t")
                    if (i%3==0&&i!=0){
                        parameters.append("\n| ")
                    }
                }

            }
        }
        val headerSb = StringBuilder()
        var newlineMarker = 150
        request.headers.forEach {
            headerSb.append(it.first).append(":").append(it.second).append("\t")
            if (headerSb.length > newlineMarker){
                newlineMarker+=150
                headerSb.append("\n").append("\t\t\t  ")
            }
        }
        logSb.append("\n| 请求头参数:$headerSb")
        logSb.append("\n| 请求参数:$parameters")
        logSb.append("\n| 返回结果:\n${content?.formatJSON()}")
        logSb.append("\n| ------------------------------------END(耗时:${System.currentTimeMillis() - startTime})------------------------------------")
        L.d("http",logSb.toString())
        return response.newBuilder()
            .body((content?:"").toResponseBody(mediaType))
            .build()
    }



    /**
     * json 字符串格式化
     */
    private fun String.formatJSON():String{
        var message: String
        message = try {
            when {
                this.startsWith("{") -> {
                    val  jsonObject =  JSONObject(this)
                    jsonObject.toString(4)
                }
                this.startsWith("[") -> {
                    val jsonArray =  JSONArray(this)
                    jsonArray.toString(4)
                }
                else -> this
            }
        } catch ( e: JSONException) {
            this
        }
        message = System.lineSeparator()+ message
        val lines = message.split(System.getProperty("line.separator")!!)
        val sb=StringBuffer()
        lines.forEach {
            sb.append(it).append("\n")
        }
        return sb.toString()
    }
}